CC := gcc
LD := ld
# Linker should relocate monitor to this address
-MONITOR_BASE := 0xFC100000
+MONITOR_BASE := 0xFC500000
# Bootloader should load monitor to this real address
LOAD_BASE := 0x00100000
CFLAGS := -fno-builtin -O3 -Wall -DMONITOR_BASE=$(MONITOR_BASE)
.long SYMBOL_NAME(gdt_table)-__PAGE_OFFSET
ALIGN
+/* NB. Rings != 0 get access up to 0xFC400000. This allows access to the */
+/* machine->physical mapping table. Ring 0 can access all memory. */
ENTRY(gdt_table)
.quad 0x0000000000000000 /* NULL descriptor */
.quad 0x0000000000000000 /* not used */
- .quad 0x00cfba000000bfff /* 0x11 ring 1 3.95GB code at 0x0 */
- .quad 0x00cfb2000000bfff /* 0x19 ring 1 3.95GB data at 0x0 */
- .quad 0x00cffa000000bfff /* 0x23 ring 3 3.95GB code at 0x0 */
- .quad 0x00cff2000000bfff /* 0x2b ring 3 3.95GB data at 0x0 */
+ .quad 0x00cfba000000c3ff /* 0x11 ring 1 3.95GB code at 0x0 */
+ .quad 0x00cfb2000000c3ff /* 0x19 ring 1 3.95GB data at 0x0 */
+ .quad 0x00cffa000000c3ff /* 0x23 ring 3 3.95GB code at 0x0 */
+ .quad 0x00cff2000000c3ff /* 0x2b ring 3 3.95GB data at 0x0 */
.quad 0x00cf9a000000ffff /* 0x30 ring 0 4.00GB code at 0x0 */
.quad 0x00cf92000000ffff /* 0x38 ring 0 4.00GB data at 0x0 */
.fill NR_CPUS,8,0 /* space for TSS's */
/* Create page table for ioremap(). */
ioremap_pt = (void *)get_free_page(GFP_KERNEL);
clear_page(ioremap_pt);
- idle0_pg_table[MAPCACHE_VIRT_START >> L2_PAGETABLE_SHIFT] =
+ idle0_pg_table[IOREMAP_VIRT_START >> L2_PAGETABLE_SHIFT] =
mk_l2_pgentry(__pa(ioremap_pt) | PAGE_HYPERVISOR);
+
+ /* Create read-only mapping of MPT for guest-OS use. */
+ idle0_pg_table[READONLY_MPT_VIRT_START >> L2_PAGETABLE_SHIFT] =
+ idle0_pg_table[RDWR_MPT_VIRT_START >> L2_PAGETABLE_SHIFT];
+ mk_l2_readonly(idle0_pg_table +
+ (READONLY_MPT_VIRT_START >> L2_PAGETABLE_SHIFT));
}
void __init zap_low_mappings (void)
ENTRY(start)
SECTIONS
{
- . = 0xFC000000 + 0x100000;
+ . = 0xFC400000 + 0x100000;
_text = .; /* Text and read-only data */
.text : {
*(.text)
net_ring_t *net_ring;
net_vif_t *net_vif;
+ /* Sanity! */
+ if ( p->domain != 0 ) BUG();
+
if ( strncmp(__va(mod[0].mod_start), "XenoGues", 8) )
{
printk("DOM%d: Invalid guest OS image\n", dom);
memset(l2tab, 0, DOMAIN_ENTRIES_PER_L2_PAGETABLE*sizeof(l2_pgentry_t));
p->mm.pagetable = mk_pagetable(phys_l2tab);
+ /* Domain 0 gets WRITE access to the read-only machine->physical table. */
+ mk_l2_writeable(l2tab + (READONLY_MPT_VIRT_START >> L2_PAGETABLE_SHIFT));
+
/*
- * NB. The upper limit on this loop does one extra page + pages for frame table.
- * This is to make sure a pte exists when we want to map the shared_info struct
- * and frame table struct.
+ * NB. The upper limit on this loop does one extra page + pages for frame
+ * table. This is to make sure a pte exists when we want to map the
+ * shared_info struct and frame table struct.
*/
ft_pages = frame_table_size >> PAGE_SHIFT;
max_page = nr_pages;
frame_table_size = nr_pages * sizeof(struct pfn_info);
frame_table_size = (frame_table_size + PAGE_SIZE - 1) & PAGE_MASK;
- free_pfns = nr_pages -
- ((MAX_MONITOR_ADDRESS + frame_table_size) >> PAGE_SHIFT);
-
- frame_table = phys_to_virt(MAX_MONITOR_ADDRESS);
+ frame_table = (frame_table_t *)FRAMETABLE_VIRT_START;
memset(frame_table, 0, frame_table_size);
+ free_pfns = nr_pages -
+ ((__pa(frame_table) + frame_table_size) >> PAGE_SHIFT);
+
/* Put all domain-allocatable memory on a free list. */
INIT_LIST_HEAD(&free_list);
- for( page_index = (MAX_MONITOR_ADDRESS + frame_table_size) >> PAGE_SHIFT;
+ for( page_index = (__pa(frame_table) + frame_table_size) >> PAGE_SHIFT;
page_index < nr_pages;
page_index++ )
{
DOMAIN_ENTRIES_PER_L2_PAGETABLE] =
mk_l2_pgentry(__pa(current->mm.perdomain_pt) | __PAGE_HYPERVISOR);
+ /*
+ * DOM0 has the MPT mapped as WRITABLE.
+ * 'p_l2_entry' happens to be pointing at the right place at this point :-)
+ */
+ if ( current->domain == 0 ) mk_l2_writeable(p_l2_entry);
+
out:
unmap_domain_mem(p_l2_entry);
return ret;
#define l1_pgentry_empty(_x) (!l1_pgentry_val(_x))
#define l2_pgentry_empty(_x) (!l2_pgentry_val(_x))
-#define __PAGE_OFFSET (0xFC000000)
+#define __PAGE_OFFSET (0xFC400000)
#define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
#define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
#define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
/* High table entries are reserved by the hypervisor. */
#define DOMAIN_ENTRIES_PER_L2_PAGETABLE \
- (PAGE_OFFSET >> L2_PAGETABLE_SHIFT)
+ (HYPERVISOR_VIRT_START >> L2_PAGETABLE_SHIFT)
#define HYPERVISOR_ENTRIES_PER_L2_PAGETABLE \
(ENTRIES_PER_L2_PAGETABLE - DOMAIN_ENTRIES_PER_L2_PAGETABLE)
#define PAGE_HYPERVISOR_RO MAKE_GLOBAL(__PAGE_HYPERVISOR_RO)
#define PAGE_HYPERVISOR_NOCACHE MAKE_GLOBAL(__PAGE_HYPERVISOR_NOCACHE)
+#define mk_l2_writeable(_p) \
+ (*(_p) = mk_l2_pgentry(l2_pgentry_val(*(_p)) | _PAGE_RW))
+#define mk_l2_readonly(_p) \
+ (*(_p) = mk_l2_pgentry(l2_pgentry_val(*(_p)) & ~_PAGE_RW))
+#define mk_l1_writeable(_p) \
+ (*(_p) = mk_l1_pgentry(l1_pgentry_val(*(_p)) | _PAGE_RW))
+#define mk_l1_readonly(_p) \
+ (*(_p) = mk_l1_pgentry(l1_pgentry_val(*(_p)) & ~_PAGE_RW))
+
+
#ifndef __ASSEMBLY__
static __inline__ int get_order(unsigned long size)
{
#ifndef __HYPERVISOR_IF_H__
#define __HYPERVISOR_IF_H__
-/* Virtual addresses beyond this are inaccessible by guest OSes. */
+/*
+ * Virtual addresses beyond this are not modifiable by guest OSes.
+ * The machine->physical mapping table starts at this address, read-only
+ * to all domains except DOM0.
+ */
#define HYPERVISOR_VIRT_START (0xFC000000UL)
typedef struct trap_info_st
#define __cacheline_aligned __attribute__((__aligned__(SMP_CACHE_BYTES)))
#define ____cacheline_aligned __cacheline_aligned
-/* 0-16MB is fixed monitor space. 0-52MB is direct-mapped at top of memory.*/
+/*** Hypervisor owns top 64MB of virtual address space. ***/
+#define HYPERVISOR_VIRT_START (0xFC000000UL)
+
+/*
+ * First 4MB are mapped read-only for all. It's for the machine->physical
+ * mapping table (MPT table). The following are virtual addresses.
+ */
+#define READONLY_MPT_VIRT_START (HYPERVISOR_VIRT_START)
+#define READONLY_MPT_VIRT_END (READONLY_MPT_VIRT_START + (4*1024*1024))
+/*
+ * Next 16MB is fixed monitor space, which is part of a 48MB direct-mapped
+ * memory region. The following are machine addresses.
+ */
#define MAX_MONITOR_ADDRESS (16*1024*1024)
#define MAX_DMA_ADDRESS (16*1024*1024)
-#define MAX_DIRECTMAP_ADDRESS (52*1024*1024)
+#define MAX_DIRECTMAP_ADDRESS (48*1024*1024)
+/* And the virtual addresses for the direct-map region... */
+#define DIRECTMAP_VIRT_START (READONLY_MPT_VIRT_END)
+#define DIRECTMAP_VIRT_END (DIRECTMAP_VIRT_START + MAX_DIRECTMAP_ADDRESS)
+#define MONITOR_VIRT_START (DIRECTMAP_VIRT_START)
+#define MONITOR_VIRT_END (MONITOR_VIRT_START + MAX_MONITOR_ADDRESS)
+#define RDWR_MPT_VIRT_START (MONITOR_VIRT_END)
+#define RDWR_MPT_VIRT_END (RDWR_MPT_VIRT_START + (4*1024*1024))
+#define FRAMETABLE_VIRT_START (RDWR_MPT_VIRT_END)
+#define FRAMETABLE_VIRT_END (DIRECTMAP_VIRT_END)
/* Next 4MB of virtual address space used for per-domain mappings (eg. GDT). */
-#define PERDOMAIN_VIRT_START (PAGE_OFFSET + MAX_DIRECTMAP_ADDRESS)
+#define PERDOMAIN_VIRT_START (DIRECTMAP_VIRT_END)
#define PERDOMAIN_VIRT_END (PERDOMAIN_VIRT_START + (4*1024*1024))
/* Penultimate 4MB of virtual address space used for domain page mappings. */
#define MAPCACHE_VIRT_START (PERDOMAIN_VIRT_END)